package com.platform.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.platform.common.bean.BaseException;
import com.platform.common.bean.SystemConfigBean;
import com.platform.common.menus.ResultCodeEnum;
import com.platform.common.menus.SysConfigEnum;
import com.platform.system.entity.SysRole;
import com.platform.system.entity.SysRoleExclude;
import com.platform.system.entity.SysUserRole;
import com.platform.system.mapper.SysUserRoleMapper;
import com.platform.system.service.SysRoleExcludeService;
import com.platform.system.service.SysRoleService;
import com.platform.system.service.SysUserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * describe:
 *
 * @author rainly
 * @date 2019/12/06
 * @time 11:31 下午
 */
@Slf4j
@Service
public class SysUserRoleServiceImpl extends ServiceImpl<SysUserRoleMapper, SysUserRole> implements SysUserRoleService {

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private SysRoleExcludeService sysRoleExcludeService;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Override
    public boolean isNotMaxUsers(String roleId) {
        if (StringUtils.isEmpty(roleId)) {
            return Boolean.FALSE;
        }
        SysRole sysRole = sysRoleService.getById(roleId);
        int maxUsers = sysRole.getMaxUsers();
        List<SysUserRole> userRoleList = sysUserRoleMapper.selectList(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
        if (CollectionUtils.isEmpty(userRoleList)) {
            return Boolean.TRUE;
        }
        return userRoleList.size() < maxUsers;
    }

    @Override
    public boolean isNotMaxUsers(List<String> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            return Boolean.FALSE;
        }
        for (String roleId : roleIds) {
            if (!isNotMaxUsers(roleId)) {
                return Boolean.FALSE;
            }
        }
        return Boolean.TRUE;
    }

    @Override
    public boolean saveBatchByUserGroup(Collection<SysUserRole> entityList) {
        List<String> roleIds = entityList.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        if (isNotMaxUsers(roleIds)) {
            return super.saveBatch(entityList);
        }
        log.info("批量保存=》角色用户基数已满，不能再关联用户");
        return Boolean.FALSE;
    }

    @Override
    public boolean save(SysUserRole entity) {
        isPlatformManager(entity.getRoleId(), entity.getUserId());
        if (isExclude(entity)) {
            if (isNotMaxUsers(entity.getRoleId())) {
                return super.save(entity);
            } else {
                log.info("角色用户基数已满，不能再关联用户，角色Id" + entity.getRoleId());
                return Boolean.FALSE;
            }
        } else {
            log.info("角色与用户存储互斥关系，角色Id" + entity.getRoleId() + " ，用户id：" + entity.getUserId());
            return Boolean.FALSE;
        }

    }

    @Override
    public boolean saveBatch(Collection<SysUserRole> entityList) {
        if (CollectionUtils.isEmpty(entityList)) {
            return Boolean.FALSE;
        }
        for (SysUserRole entity : entityList) {
            isPlatformManager(entity.getRoleId(), entity.getUserId());
            if (isExclude(entity)) {
                log.info("角色与用户存储互斥关系，角色Id" + entity.getRoleId() + " ，用户id：" + entity.getUserId());
                return Boolean.FALSE;
            }
        }

        List<String> roleIds = entityList.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        if (isNotMaxUsers(roleIds)) {
            return super.saveBatch(entityList);
        }
        log.info("批量保存=》角色用户基数已满，不能再关联用户");
        return Boolean.FALSE;
    }

    /**
     * 判断角色和用户是否有互斥关系
     *
     * @param userRole SysUserRole
     * @return true 有
     */
    private boolean isExclude(SysUserRole userRole) {
        //静态职责
        if (Objects.equals(SysConfigEnum.SeparationOfDuty.SSD.getValue(), SystemConfigBean.getInstance().getSeparationOfDuty())) {
            //与添加角色有互斥的角色
            List<SysRoleExclude> excludeList = sysRoleExcludeService.selectExcludeRoleId(userRole.getRoleId());
            List<String> excludeRoleIds = Optional.ofNullable(excludeList)
                    .map(e -> e.stream().map(SysRoleExclude::getRoleId).collect(Collectors.toList()))
                    .orElse(new ArrayList<>());

            //用户的角色
            List<SysUserRole> userRoles = sysUserRoleMapper.selectList(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userRole.getUserId()));
            List<String> userRoleIds = Optional.ofNullable(userRoles)
                    .map(u -> u.stream().map(SysUserRole::getRoleId).collect(Collectors.toList()))
                    .orElse(new ArrayList<>());

            return Collections.disjoint(excludeRoleIds, userRoleIds);
        }
        return Boolean.FALSE;
    }

    private void isPlatformManager(String roleId, String userId) {
        //平台管理员角色 不能再添加到任何用户组
        SysRole platformManagerRole = sysRoleService.selectPlatformRole();
        if (platformManagerRole == null) {
            throw new BaseException(ResultCodeEnum.FAILURE, "平台管理员角色缺少，请联系管理员");
        }
        if (Objects.equals(roleId, platformManagerRole.getRoleId())) {
            throw new BaseException(ResultCodeEnum.FAILURE, "不能添加平台管理员角色");
        }

        //平台管理员 不能再添加到任何用户组
        List<SysUserRole> sysUserRoleList = sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, platformManagerRole.getRoleId()));
        List<String> platformManagers = Optional.ofNullable(sysUserRoleList)
                .map(sysUserRoles -> sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList()))
                .orElse(new ArrayList<>());
        if (platformManagers.contains(userId)) {
            throw new BaseException(ResultCodeEnum.FAILURE, "不能添加平台管理员");
        }

    }
}
